﻿namespace Contoso.ActiveDirectory {

    #region Usings
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.DirectoryServices;
    using System.Linq;
    using System.Text;
    using System.Threading; 
    #endregion

    [Serializable]
    public class ExchangeActiveSyncDevices : ADBaseObjectProperties, IExchangeActiveSyncDevices {

        #region Members
        private static readonly string ActiveSyncDevicesTag = "CN=ExchangeActiveSyncDevices,";
        public static readonly string ObjectCategoryShortName = "msExchActiveSyncDevices";

        public IReadOnlyList<ExchangeActiveSyncDevice> Devices { get; private set; }
        public int MSExchObjectsDeletedThisPeriod { get; private set; }
        public long MSExchVersion { get; private set; }

        /// <summary>
        /// The distinguished name of the UserAccount that owns this ActiveSync device
        /// </summary>
        public string OwnerMailboxDN {
            get {
                string ownerMailboxDN = string.Empty;
                // CN=iPhone§ApplF2ABCDE2ABCD,CN=ExchangeActiveSyncDevices,CN=xxxxxxx,OU=Users,OU=HQ,DC=contoso,DC=com
                if (!string.IsNullOrWhiteSpace(this.DN)) {
                    if (this.DN.IndexOf(ActiveSyncDevicesTag, StringComparison.OrdinalIgnoreCase) > -1) {
                        ownerMailboxDN = this.DN.Substring(this.DN.IndexOf(ActiveSyncDevicesTag, StringComparison.OrdinalIgnoreCase));
                        if (ownerMailboxDN.Length > ActiveSyncDevicesTag.Length) {
                            ownerMailboxDN = ownerMailboxDN.Substring(ActiveSyncDevicesTag.Length);
                        }
                    }
                }

                return ownerMailboxDN;
            }

        }
        #endregion

        #region Constructor
        public ExchangeActiveSyncDevices() {
            this.Initialize();
        } 

        public ExchangeActiveSyncDevices(DirectoryEntry directoryEntry, bool destroyInputObject = true)
            : base(directoryEntry, destroyInputObject) {
                if (this.GetType().Name == typeof(ExchangeActiveSyncDevices).Name) {
                this.Attributes = null;
            }
        }

        public ExchangeActiveSyncDevices(SearchResult result, bool destroyInputObject = true)
            : base(result, destroyInputObject) {
                if (this.GetType().Name == typeof(ExchangeActiveSyncDevices).Name) {
                this.Attributes = null;
            }
        }

        public ExchangeActiveSyncDevices(List<string> ldifOutput)
            : base(ldifOutput) {
                if (this.GetType().Name == typeof(ExchangeActiveSyncDevices).Name) {
                this.Attributes = null;
            }
        }
        #endregion

        #region Methods
        public void GetExchangeActiveSyncDevices() {
            string filter = "objectCategory=" + ExchangeActiveSyncDevice.ObjectCategoryShortName;
            this.Devices = ADDataAccess.GetADObjectProperties<ExchangeActiveSyncDevice>(
                this.DN, null, filter, PartitionScope.LocalPartition);
        }

        protected override void Initialize() {
            base.Initialize();

            this.Devices = new List<ExchangeActiveSyncDevice>();
        }

        protected override void ProcessResults() {

            try {
                base.ProcessResults();

                if (this.Attributes.ContainsKey("msExchVersion")) {
                    this.MSExchVersion = Convert.ToInt64(this.Attributes["MSExchVersion"][0]);
                }
                if (this.Attributes.ContainsKey("msExchObjectsDeletedThisPeriod")) {
                    this.MSExchObjectsDeletedThisPeriod = Convert.ToInt32(this.Attributes["msExchObjectsDeletedThisPeriod"][0]);
                }
                this.GetExchangeActiveSyncDevices();

                this.IsValid = !string.IsNullOrWhiteSpace(this.DN)
                    && this.ObjectClass.Any(x => string.Equals(x, ObjectCategoryShortName, StringComparison.OrdinalIgnoreCase));            
            }
            catch (Exception e) {
                Debug.WriteLine(string.Format("{0}  [ThreadID: {1}]  {2} Error: {3}", DateTime.Now.TimeOfDay, Thread.CurrentThread.ManagedThreadId, CustomExtensions.CurrentMethodName(), e.VerboseExceptionString()));
                throw;
            }
        }
        #endregion
    }
}
